package com.gitee.huanminabc.fastboot.web.servlet;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gitee.huanminabc.fastboot.web.annotation.http.RequestParam;
import com.gitee.huanminabc.fastboot.web.context.ApiThreadContext;
import com.gitee.huanminabc.fastboot.web.exception.ApiDataConvertException;
import com.gitee.huanminabc.fastboot.web.exception.ApiParamNonSupportException;
import com.gitee.huanminabc.jcommon.reflect.AnnotationUtil;
import com.gitee.huanminabc.jcommon.reflect.ClassIdentifyUtil;
import com.gitee.huanminabc.jcommon.reflect.EnumUtil;
import com.gitee.huanminabc.jcommon.reflect.GenericUtil;
import com.gitee.huanminabc.jcommon.str.StringTypeCastUtil;
import com.gitee.huanminabc.jcommon.str.StringUtil;
import com.gitee.huanminabc.nullchain.Null;
import com.gitee.huanminabc.nullchain.enums.DateFormatEnum;
import io.netty.handler.codec.http.multipart.FileUpload;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.temporal.Temporal;
import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 * 简要描述
 *
 * @Author: huanmin
 * @Date: 2025/4/1 22:57
 * @Version: 1.0
 * @Description: 文件作用详细描述....
 */
public class MethodParameterBound {


    public static Object[] getMethodParameterBound(JSONObject args, Method method) {
        Parameter[] parameters = method.getParameters();
        Object[] result = new Object[parameters.length];
        for (int i = 0; i < parameters.length; i++) {
            Parameter parameter = parameters[i];
            Class<?> type = parameter.getType();

            //处理文件上传的参数
            Object file = fileUploadBound(type, args);
            if (file != null) {
                result[i] = file;
                continue;
            }

            boolean baseType = ClassIdentifyUtil.isInlayGeneralType(type);
            RequestParam paramAnnotation = AnnotationUtil.getParamAnnotation(parameter, RequestParam.class);
            if (paramAnnotation == null && baseType) {
                //尝试从参数名称中获取
                String key = parameter.getName();
                Object v = args.get(key);
                if (v == null) {
                    throw new ApiParamNonSupportException(type.getName(), ApiThreadContext.get().getInterfaceMethodDefDesc(), "没有找到需要绑定的参数 " + key);
                }
                result[i] = castParams(v, type);//如果没有就是空
            }else if (paramAnnotation != null && baseType) {
                String key = paramAnnotation.value();
                if (StringUtil.isEmpty(key)) {
                    key= parameter.getName();
                }
                Object v = args.get(key);
                if (v == null && paramAnnotation.required()) {
                    if (StringUtil.isNotEmpty(paramAnnotation.defaultValue())) {
                        result[i] = castParams(paramAnnotation.defaultValue(), type);
                    } else {
                        throw new ApiParamNonSupportException(type.getName(), ApiThreadContext.get().getInterfaceMethodDefDesc(), "请求中没有参数" + key);
                    }
                } else {
                    if (v != null) {
                        result[i] = castParams(v, type);//如果没有就是空
                    }
                }
            } else {
                //如果没有标识,那么就表示是对象 ,尝试将值转换过去, 最少也是一个空的对象不是null,这样保证接口入参对象不是null

                Object args1 = args.get("$args1$");
                if (args1 != null) {
                    if (args1 instanceof JSONArray) {
                        //如果type是数组类型,那么就需要转换成数组
                        if (type.isArray()) {
                            result[i]= JSONArray.parseArray(args1.toString(), type.getComponentType());
                        }else  if (Collection.class.isAssignableFrom(type)) {
                            Class<?> classGenericType = GenericUtil.getParameterGenericType(parameter, 0);
                            if (classGenericType == null) {
                                throw new ApiParamNonSupportException(type.getName(), ApiThreadContext.get().getInterfaceMethodDefDesc(), "集合类型没有指定泛型");
                            }
                            result[i] = JSONArray.parseArray(args1.toString(), classGenericType);
                        }
                    }else{
                        result[i] =castParams(args1,type);
                    }
                }else{
                    result[i] = args.toJavaObject(type);
                }
            }
        }
        return result;
    }

    private static Object castParams(Object value, Class<?> type) {
        if (Temporal.class.isAssignableFrom(type) || Date.class.isAssignableFrom(type)) {
            String data = Null.ofDate(value).dateFormat(DateFormatEnum.DATETIME_PATTERN).get();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(data);
            try {
                return simpleDateFormat.parse(data);
            } catch (Exception e) {
                throw new ApiDataConvertException(ApiThreadContext.get().getInterfaceMethodDefDesc(), type, value.toString());
            }
        }
        if (BigDecimal.class.isAssignableFrom(type)) {
            return new BigDecimal(value.toString());
        }
        //如果是枚举类型,那么就
        if (type.isEnum()){
            return EnumUtil.castEnum(value,type);
        }
        return StringTypeCastUtil.cast(value.toString(), type);
    }


    private static Object fileUploadBound(Class<?> type, JSONObject args) {
        Object $fileList$ = args.get("$fileList$");
        if ($fileList$ == null) {
            return null;
        }
        List<FileUpload> files = (List<FileUpload>) $fileList$;
        if (type == FileUpload.class) {
            //获取args里面第一个FileUpload
            return files.get(0);
        } else if (type == FileUpload[].class) {
            return files.toArray(new FileUpload[0]);
        }
        return null;
    }

}
